package com.behelpful.common.core.jackson.sensitive;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.util.Objects;

/**
 * String 类型脱敏序列化
 *
 * @author Alay
 * @date 2021-09-10 10:20
 * @see {参考博客：https://blog.csdn.net/liufei198613/article/details/79009015}
 */
@NoArgsConstructor
@AllArgsConstructor
public class StringSensitiveSerializer extends JsonSerializer<String> implements ContextualSerializer {

    private SensitiveTypeEnum type;

    private Integer prefixNoMaskLen;

    private Integer suffixNoMaskLen;

    private String maskStr;


    @Override
    public void serialize(String origin, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        switch (type) {
            case CHINESE_NAME:
                jsonGenerator.writeString(DesensitizedUtil.chineseName(origin));
                break;
            case SEX:
                jsonGenerator.writeString(DesensitizedUtil.sex(origin));
                break;
            case ID_CARD:
                jsonGenerator.writeString(DesensitizedUtil.idCardNum(origin));
                break;
            case FIXED_PHONE:
                jsonGenerator.writeString(DesensitizedUtil.fixedPhone(origin));
                break;
            case MOBILE_PHONE:
                jsonGenerator.writeString(DesensitizedUtil.mobilePhone(origin));
                break;
            case ADDRESS:
                jsonGenerator.writeString(DesensitizedUtil.address(origin));
                break;
            case EMAIL:
                jsonGenerator.writeString(DesensitizedUtil.email(origin));
                break;
            case BANK_CARD:
                jsonGenerator.writeString(DesensitizedUtil.bankCard(origin));
                break;
            case PASSWORD:
                jsonGenerator.writeString(DesensitizedUtil.password(origin));
                break;
            case KEY:
                jsonGenerator.writeString(DesensitizedUtil.key(origin));
                break;
            case CUSTOMER:
                jsonGenerator.writeString(DesensitizedUtil.desValue(origin, prefixNoMaskLen, suffixNoMaskLen, maskStr));
                break;
            default:
                throw new IllegalArgumentException("Unknown sensitive type enum " + type);
        }
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        if (null != beanProperty) {
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
                Sensitive sensitive = beanProperty.getAnnotation(Sensitive.class);
                if (sensitive == null) {
                    sensitive = beanProperty.getContextAnnotation(Sensitive.class);
                }
                if (sensitive != null) {
                    return new StringSensitiveSerializer(sensitive.type(), sensitive.maskStartLen(),
                            sensitive.keepTailLen(), sensitive.maskStr());
                }
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }
}
